﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;

namespace FAST
{
    public class Main
    {
        private UpdateDetection ud;
        private UpdateReconcilation ur;
        private Session sess;
        private OriginalState leftOS, rightOS;
        private string leftOSPath, rightOSPath;

        public Main() //exclude ui item
        {
            ud = new UpdateDetection();
            ur = new UpdateReconcilation();
           
            sess = new Session();

            SessionItem sessItem = sess.getLastLoadedSession();
            if (sessItem != null)
            {
                leftOSPath = sessItem.getNewOriginalStatePathLeft();
                rightOSPath = sessItem.getNewOriginalStatePathRight();
            }
            else
            {
                leftOSPath = "";
                rightOSPath = "";
            }
 
            leftOS = new OriginalState(leftOSPath); //use default file to write path
            rightOS = new OriginalState(rightOSPath); //use default file to write path
        }

        //can remove later (temp)
        public void refreshSession()
        {
            sess = new Session();
        }

        //Method name : previewOnly() : void
        //Parameters  : src(type string), des(type string)
        //Description : Generate Left/right list of FilesHandler object comparing with OriginalState if exist.
        //Exceptions  :  PathTooLongException: When the path string exceed 256 characters string size limit.
        public void previewOnly(string src, string des)
        {
            ud.processLeftFolder(src);
            ud.processRightFolder(des);
        }

        public void previewWithoutOS(string src, string des)//method use with balancing listview
        {
            ud.removeOS();
            ud.processLeftFolder(src);
            ud.processRightFolder(des);
        }

        public List<FilesHandler> generateLeftTree()
        {
            return ud.getLeftFolderList();
        }

        public List<FilesHandler> generateRightTree()
        {
            return ud.getRightFolderList();
        }

        //Method name : twoWaySync() : MessageLog
        //Parameters  : src(type string), des(type string)
        //Description :  Retrieve left/right list of FilesHandler object, process the status, create session if it does not exist and sync data across drive. 
        //Exceptions  :  IndexOutOfRangeException: Shifting position of list may incur this exception, FileNotFoundException: Invalid source or destination file path, DirectoryNotFoundException: Invalid source or destination directory path, UnauthorizedAccessException: Copy Read-only file to destination.
        public MessageLog twoWaySync(string src, string des)
        {
            try
            {
                ud.processLeftFolder(src);
                ud.processRightFolder(des);

                List<FilesHandler> leftList = ud.getLeftFolderList();
                List<FilesHandler> rightList = ud.getRightFolderList();

                ur.processStatus(leftList, rightList, src, des);

                //assume both left and right list same unless LModRDelete/RModLDelete conflict

                if (sess.getSessionsCount() == 0)
                    sess.createNewSession();

                sess.updateSession(src,des,leftList,rightList);//update os and versioning of current session, ie latest added session

                //check if system data exist in another drive and sync if necessary.
                syncData(src, des);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
                return ur.generateMsgLog();
            
        }

        public void syncData(string src, string des)
        {
            // Display src drive information.
            DriveInfo srcDrive = new DriveInfo(src);
            // Display des drive information.
            DriveInfo desDrive = new DriveInfo(des);
            try
            {
                if (!srcDrive.Name.Equals(desDrive.Name))
                {
                    DirectoryInfo sourcedinfo = new DirectoryInfo(Application.StartupPath);
                    DirectoryInfo destinfo = new DirectoryInfo(Path.Combine(desDrive.Name, @"Sessions"));

                    DirectoryInfo di = new DirectoryInfo(Application.StartupPath + @"\Sessions");
                    //DirectoryInfo desDi = new DirectoryInfo(destinfo.ToString() + @"\Session");
                    //Hide and Disallow user to access the storage file.
                    copyAllFiles(di, destinfo);
                    File.Copy(Application.StartupPath + @"\session.dat", desDrive.Name + @"\session.dat", true);
                    File.SetAttributes(Path.Combine(desDrive.Name, @"Sessions"), FileAttributes.ReadOnly | FileAttributes.Hidden);

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }          
        }

        public void copyAllFiles(DirectoryInfo source, DirectoryInfo target)
        {
            try
            {
                // Check if the target directory exists, if not, create it.
                if (Directory.Exists(target.FullName) == false)
                {
                    Directory.CreateDirectory(target.FullName);
                }

                // Copy each file into it’s new directory.
                foreach (FileInfo fi in source.GetFiles())
                {
                    Console.WriteLine(@"Copying {0}\{1}", target.FullName, fi.Name);
                    fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
                }

                // Copy each subdirectory using recursion.
                foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
                {
                    DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
                    copyAllFiles(diSourceSubDir, nextTargetSubDir);
                }
            }
            catch (Exception)
            {
            }
        }

        public string getSessionLog()
        {
            return sess.getLastLoadedSessionLog();
        }

        public void clearCurrentSession()
        {
            sess.removeLastLoadedSession();
        }

        public bool isSessionsEmpty()
        {
            return (sess.getSessionsCount() == 0);
        }

        public void createNewSession()
        {
            sess.createNewSession();
            sess = new Session();
        }

        public List<SessionItem> retrieveSessions()
        {
            return sess.getSessions();
        }

        public void loadSessionByIdx(int idx)
        {
            sess.setUpdateIndex(idx);
        }

        public string getSessionLeftFolderPath()
        {
            return sess.getSessionLeftFolderPath();
        }

        public string getSessionRightFolderPath()
        {
            return sess.getSessionRightFolderPath();
        }

        public int getLoadedSessionIndex()
        {
            return sess.getLoadedIdx();
        }

        //versioning
        public List<FileVersioningList> getFVList()
        {
            FileVersioning fv = new FileVersioning();
            return fv.getListOfFVList();
        }

        public List<FileHandler> getVersionList(int index)
        {
            List<FileVersioningList> fileVersionList;
            List<FileHandler> FVList;
            FileVersioning fv = new FileVersioning();
            fileVersionList = fv.getListOfFVList();
            FVList = fv.getListOfFVList()[index].getListOfFH();
            return FVList;
        }

        public void setVersionList(List<FileHandler> vList, int idx)
        {
            FileVersioning fv = new FileVersioning();
            fv.setVersionListByIdx(vList, idx);
        }
    }
}
